#include "StdAfx.h"
#include "Quote.h"
#include "./ThirdPart/tinyxml/Include/tinyxml.h"
#include "CTPQuote.h"
#include "./ThirdPart/Log.h"

CQuote::CQuote(void)
{
}

CQuote::~CQuote(void)
{
}

void CQuote::Start()
{
	if(!LoadConfig())
	{
		CLog::Log("load config err,check xml formate...");

		return;
	}

	if(!InitCTP())
	{
		CLog::Log("ctp dll init err...");

		return;
	}

	if (!InitNetwork())
	{
		CLog::Log("network init err...");
		return;
	}

	CLog::Log("programme is running...");
}

void CQuote::End()
{
	m_net.EndService();

	Logout();
}

bool CQuote::LoadConfig()
{
	USES_CONVERSION;

	TiXmlDocument doc;
	if (!doc.LoadFile(W2CA(CONFIG_FILE)))
	{
		return false;
	}

	TiXmlHandle handle(&doc);
	//Account
	TiXmlElement* pNode = handle.FirstChild("Quote").FirstChild("Account").ToElement();
	if (pNode)
	{
		const char *Broker			= pNode->Attribute("Broker");
		const char *Investor		= pNode->Attribute("Investor");
		const char *Password		= pNode->Attribute("Password");
		const char *QuoteAdress		= pNode->Attribute("QuoteAdress");

		if (!Broker || !Investor || !Password || !QuoteAdress)
		{
			return false;
		}

		_snwprintf_s(m_Account.m_szBroker,MAX_ACCOUNT_LEN,L"%s",A2T(Broker));
		_snwprintf_s(m_Account.m_szInvestor,MAX_ACCOUNT_LEN,L"%s",A2T(Investor));
		_snwprintf_s(m_Account.m_szPassword,MAX_PASSWORD_LEN,L"%s",A2T(Password));
		_snwprintf_s(m_Account.m_szQuoteAddress,MAX_ADDRESS_LEN,L"%s",A2T(QuoteAdress));
	}
	else return false;


	//Instrument
	pNode = handle.FirstChild("Quote").FirstChild("Instruments").ToElement();
	if (pNode)
	{
		int count = 0;
		const char *ret = pNode->Attribute("Count",&count);
		if (!ret)
		{
			return false;
		}

		pNode = handle.FirstChild("Quote").FirstChild("Instruments").FirstChild("Instrument").ToElement();
		while(pNode)
		{
			const char *id = pNode->Attribute("ID");

			Instrument in ;
			sprintf(in.instrument,"%s",id);
			m_lInstrument.push_back(in);

			pNode = pNode->NextSiblingElement("Instrument");
		}

	}
	else return false;

	//mysql
	pNode = handle.FirstChild("Quote").FirstChild("mysql").ToElement();
	if (pNode)
	{
		const char *ip = pNode->Attribute("ip");
		const char *port = pNode->Attribute("port");
		const char *db = pNode->Attribute("dbname");
		const char *user = pNode->Attribute("user");
		const char *pwd = pNode->Attribute("password");

		if (!ip || !port || !db || !user || !pwd)
		{
			return false;
		}

		sprintf(m_sqlAccount.m_host_addr,"%s",ip);
		sprintf(m_sqlAccount.m_username,"%s",user);
		sprintf(m_sqlAccount.m_password,"%s",pwd);
		sprintf(m_sqlAccount.m_database_name,"%s",db);
		m_sqlAccount.m_port = atoi(port);

	}
	else return false;

	//server
	pNode = handle.FirstChild("Quote").FirstChild("server").ToElement();
	if (pNode)
	{
		const char *ip = pNode->Attribute("ip");
		const char *port = pNode->Attribute("port");
		sprintf(m_netConfig.m_szIP,"%s",ip);
		m_netConfig.m_port = atoi(port);
	}
	else return false;


	return true;
}


bool CQuote::InitCTP()
{
	USES_CONVERSION;

	m_api = CThostFtdcMdApi::CreateFtdcMdApi("./thostmduserapi.dll");

	if (!m_api)
	{
		return false;
	}

	m_spi = new CCTPQuote();

	m_api->RegisterSpi(m_spi);
	m_api->RegisterFront(T2A(m_Account.m_szQuoteAddress));
	m_api->Init();

	return true;
}	

bool CQuote::InitNetwork()
{
	//m_net.SetMaxSocketItem(65535);
	//m_net.SetServicePort(m_netConfig.m_port);

	static CNetFrame frame;
	return m_net.BeginService(frame.GetAttemperEngineSink());
}

int CQuote::Login()
{
	USES_CONVERSION;

	CThostFtdcReqUserLoginField f;
	memset(&f, 0, sizeof(CThostFtdcReqUserLoginField));
	strcpy_s(f.BrokerID, sizeof(f.BrokerID), T2A(m_Account.m_szBroker));
	strcpy_s(f.UserID, sizeof(f.UserID), T2A(m_Account.m_szInvestor));
	strcpy_s(f.Password, sizeof(f.Password), T2A(m_Account.m_szPassword));
	return m_api->ReqUserLogin(&f, ++m_LoingReq);
}

void CQuote::Logout()
{
	if (!m_api)
	{
		return;
	}

	m_api->RegisterSpi(NULL);
	m_api->Release();
}


int CQuote::SubMarketData(char *pInstrumentID)
{
	char *insts[] = { pInstrumentID };
	return m_api->SubscribeMarketData(insts, 1);
}

int CQuote::UnSubMarketData(char *pInstrumentID)
{
	char *insts[] = { pInstrumentID };
	return m_api->UnSubscribeMarketData(insts, 1);
}

bool CQuote::LoginDB()
{
	m_dbInfo.init();

	char errmsg[SQL_ERR_LEN]={0};
	int ret = DB_CONTROL->set_db(&m_dbInfo,m_sqlAccount.m_host_addr,m_sqlAccount.m_port,m_sqlAccount.m_username,m_sqlAccount.m_password,m_sqlAccount.m_database_name,errmsg);

	if(ret != SUCCESS)
	{
		CLog::Log(errmsg);
	}
	else
	{
		CLog::Log("Login DB ok...");
	}

	return ret == SUCCESS;
}

//////////////////////////////////////////////////////////////////////////

void CQuote::OnFrontConnected()
{
	Login();

	CLog::Log("front is connected,do login...");
}	

void CQuote::OnRspUserLogin(int errid)
{
	for (lInstrumentIter it = m_lInstrument.begin();it!=m_lInstrument.end();++it)
	{
		SubMarketData(it->instrument);
	}

	CLog::Log("login ok,do subInstrument,do login db...");

	if(!LoginDB())
	{
		CLog::Log("db login err,instrument data will not write to db...");
	}

}	

void CQuote::OnRspUserLogout(int reason)
{

}	

void CQuote::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData)
{
	//TRACE("market data:%s,%0.1f\n",pDepthMarketData->InstrumentID,pDepthMarketData->OpenPrice);

}	

void CQuote::OnRtnError(int errid,char * errmsg)
{

}	
